home *** CD-ROM | disk | FTP | other *** search
- { Vector Engine Source File }
- { PHRO! }
- { Phred/OTM }
- { achalfin@uceng.uc.edu }
- { DO NOT DISTRIBUTE THIS SOURCE FILE }
-
- Unit Vector;
-
- Interface
-
- Const
- cGouraudPoly = 1;
- cPhongPoly = 2;
-
- Procedure InitVectorRoutines(NumtoSort : Integer);
- Procedure CloseVectorRoutines;
- Procedure SelectEnable(Num, Ena : Byte; EnMap : Pointer);
- Procedure Location(Num, tx, ty, tz, ax, ay, az : Longint);
- Procedure LoadVectorObject(Data : Pointer; NumVecObjects, Shading : Byte);
- Procedure DisplayVectorObjects(VPage : Word);
- Procedure FreeVectorObject(Num : Byte);
-
- Implementation
-
- Uses Polygons;
-
- Type
- SCoord = Record { Screen coordinate }
- x, y : Integer;
- End;
- LCoord = Record { Vertex & Normal coordinate }
- x, y, z : Longint;
- End;
- PolygonDef = Record
- p1, p2, p3 : Integer;
- End;
- TPolygonList = Array[0..1000] of PolygonDef;
- PPolygonList = ^TPolygonList;
- TCoordList = Array[0..1000] of LCoord;
- PCoordList = ^TCoordList;
- TScreenCoord = Array[0..1000] of SCoord;
- PScreenCoord = ^TScreenCoord;
- PSortRec = ^PhongSortRec;
- PhongSortRec = Record
- ZMid : Integer;
- PolyType : Byte;
- OwnerIndex : Byte;
- Next : PSortRec; { 4 Bytes }
- Index : Integer; { 2 Bytes }
- Theta1, Phi1 : Byte; { 2 Bytes }
- Theta2, Phi2 : Byte; { 2 Bytes }
- Theta3, Phi3 : Byte; { 2 Bytes }
- { Exactly 16 bytes. For faster indexing }
- End;
- GSortRec = ^GouraudSortRec;
- GouraudSortRec = Record
- ZMid : Integer;
- PolyType : Byte;
- OwnerIndex : Byte;
- Next : PSortRec; { 4 Bytes }
- Index : Integer; { 2 Bytes }
- C1, C2, C3 : Byte; { 3 Bytes }
- Base : Byte;
- T1, T2 : Byte; { 3 Bytes }
- { Exactly 16 bytes. For faster indexing }
- End;
- TRotateList = Array[0..5000] of Byte;
- PRotateList = ^TRotateList;
- TSortList = Array[0..3000] of PhongSortRec;
- PSortList = ^TSortList;
- TByteList = Array[0..255] of PSortRec;
- PByteList = ^TByteList;
- DotRec = Record
- Viewer, XAxis, YAxis : Longint;
- End;
- tVectorObject = Record
- LocalVert : pCoordList;
- WorldVert : pCoordList;
- ScreenVert : pScreenCoord;
- Normals : pCoordList;
- VertNorms : pCoordList;
- Polygons : pPolygonList;
- RotateList : pRotateList;
- NumVert : Integer;
- NumFacet : Integer;
- ShadeType : Byte;
- Enabled : Byte;
- EnvMap : Pointer;
- xt, yt, zt : Longint;
- xa, ya, za : Word;
- DotList : Array[0..1000] of DotRec;
- End;
-
- Var
- SortList : PSortList;
- VectorObjects : Array[0..3] of tVectorObject;
- ObjectViewer : LCoord;
- XAxis, YAxis : LCoord;
- MSBList : PByteList;
- MaxSort : Integer;
-
- Procedure Location(Num, tx, ty, tz, ax, ay, az : Longint);
-
- Begin
- VectorObjects[Num].xa := ax;
- VectorObjects[Num].ya := ay;
- VectorObjects[Num].za := az;
- VectorObjects[Num].xt := tx;
- VectorObjects[Num].yt := ty;
- VectorObjects[Num].zt := tz;
- End;
-
- Procedure InitVectorRoutines(NumtoSort : Integer);
-
- Begin
- MaxSort := NumToSort;
- Getmem(SortList, NumToSort*Sizeof(PhongSortRec));
- FillChar(VectorObjects, Sizeof(VectorObjects), 0);
- End;
-
- Procedure CloseVectorRoutines;
-
- Begin
- Freemem(SortList, MaxSort*Sizeof(PhongSortRec));
- FillChar(VectorObjects, Sizeof(VectorObjects), 0);
- End;
-
- Procedure SelectEnable(Num, Ena : Byte; EnMap : Pointer);
-
- Begin
- VectorObjects[Num].Enabled := Ena;
- VectorObjects[Num].EnvMap := EnMap;
- End;
-
- Procedure FreeVectorObject(Num : Byte);
-
- Begin
- With VectorObjects[Num] do
- Begin
- Freemem(LocalVert, NumVert*Sizeof(LCoord));
- Freemem(WorldVert, NumVert*Sizeof(LCoord));
- Freemem(VertNorms, NumVert*Sizeof(LCoord));
- Freemem(ScreenVert, NumVert*Sizeof(SCoord));
- Freemem(RotateList, NumFacet*Sizeof(Byte));
- Freemem(Normals, NumFacet*Sizeof(LCoord));
- Freemem(Polygons, NumFacet*Sizeof(PolygonDef));
- End;
- End;
-
- {$F+}
- {$L Mat.OBJ}
- Procedure InitRotationMatrix(x, y, z : Integer); External;
- Procedure Rotate(Var Local, World, Screen, Mask; Num : Word; X, Y, Z : Longint); External;
- Procedure SingleRotate(Var Vertex; X, Y, Z : Word); External;
-
- {$L ByteSort.Obj}
- Procedure ByteSort(Var PolyList; Num : Word; Var List : PByteList); External;
-
- {$L Dot.Obj}
- Function DotProduct(Var V1, V2) : Longint; External;
- {$F-}
-
-
- Procedure LoadVectorObject(Data : Pointer; NumVecObjects, Shading : Byte);
-
- Var
- VecSeg, VecOfs : Word;
- Temp : Integer;
- Count : Integer;
-
- Begin
- VecSeg := Seg(Data^);
- VecOfs := Ofs(Data^);
- Temp := MemW[VecSeg:VecOfs]; { Read Flag }
- Inc(VecOfs, 2);
- VectorObjects[NumVecObjects].NumVert := MemW[VecSeg:VecOfs];
- Inc(VecOfs, 2);
- With VectorObjects[NumVecObjects] do
- Begin
- Getmem(LocalVert, NumVert*Sizeof(LCoord));
- Getmem(WorldVert, NumVert*Sizeof(LCoord));
- Getmem(VertNorms, NumVert*Sizeof(LCoord));
- Getmem(ScreenVert, NumVert*Sizeof(SCoord));
- End;
- For Count := 0 to (VectorObjects[NumVecObjects].Numvert-1) do
- Begin
- Temp := MemW[VecSeg:VecOfs];
- Inc(VecOfs, 2);
- VectorObjects[NumVecObjects].LocalVert^[Count].x := Temp;
- Temp := MemW[VecSeg:VecOfs];
- Inc(VecOfs, 2);
- VectorObjects[NumVecObjects].LocalVert^[Count].y := Temp;
- Temp := MemW[VecSeg:VecOfs];
- Inc(VecOfs, 2);
- VectorObjects[NumVecObjects].LocalVert^[Count].z := Temp;
- End;
- VectorObjects[NumVecObjects].NumFacet := MemW[VecSeg:VecOfs];
- Inc(VecOfs, 3); { Read numpolys, and vif }
- With VectorObjects[NumVecObjects] do
- Begin
- Getmem(Polygons, NumFacet*Sizeof(PolygonDef));
- Getmem(Normals, NumFacet*Sizeof(LCoord));
- Getmem(RotateList, NumFacet*Sizeof(Byte));
- End;
- For Count := 0 to (VectorObjects[NumVecObjects].NumFacet-1) do
- Begin
- Temp := MemW[VecSeg:VecOfs];
- Inc(VecOfs, 2);
- VectorObjects[NumVecObjects].Polygons^[Count].p1 := Temp;
- Temp := MemW[VecSeg:VecOfs];
- Inc(VecOfs, 2);
- VectorObjects[NumVecObjects].Polygons^[Count].p2 := Temp;
- Temp := MemW[VecSeg:VecOfs];
- Inc(VecOfs, 2);
- VectorObjects[NumVecObjects].Polygons^[Count].p3 := Temp;
- End;
- For Count := 0 to (VectorObjects[NumVecObjects].NumFacet-1) do
- Begin
- Temp := MemW[VecSeg:VecOfs];
- Inc(VecOfs, 2);
- VectorObjects[NumVecObjects].Normals^[Count].x := Temp*2;
- Temp := MemW[VecSeg:VecOfs];
- Inc(VecOfs, 2);
- VectorObjects[NumVecObjects].Normals^[Count].y := Temp*2;
- Temp := MemW[VecSeg:VecOfs];
- Inc(VecOfs, 2);
- VectorObjects[NumVecObjects].Normals^[Count].z := Temp*2;
- End;
- For Count := 0 to (VectorObjects[NumVecObjects].Numvert-1) do
- Begin
- Temp := MemW[VecSeg:VecOfs];
- Inc(VecOfs, 2);
- VectorObjects[NumVecObjects].VertNorms^[Count].x := Temp*2;
- Temp := MemW[VecSeg:VecOfs];
- Inc(VecOfs, 2);
- VectorObjects[NumVecObjects].VertNorms^[Count].y := Temp*2;
- Temp := MemW[VecSeg:VecOfs];
- Inc(VecOfs, 2);
- VectorObjects[NumVecObjects].VertNorms^[Count].z := Temp*2;
- End;
- VectorObjects[NumVecObjects].ShadeType := Shading;
- End;
-
- Procedure CreateRotateList(Var SortCount : Integer; NumUse : Integer);
- { Creates the vertex mask table and the sort list }
- { Returns the number of polygons in the sort list }
-
- Var
- Count : Integer;
- Dot : Longint;
- SortStart : Integer;
-
- Begin
- SortStart := SortCount;
- With VectorObjects[NumUse] do
- Begin
- For Count := 0 to (NumFacet-1) do
- Begin
- Dot := DotProduct(ObjectViewer, Normals^[Count]);
- If Dot >= 0
- Then Begin
- With SortList^[SortCount] do
- Begin
- Index := Count;
- Next := Nil;
- OwnerIndex := NumUse;
- PolyType := ShadeType;
-
- End;
- RotateList^[Polygons^[Count].p1] := 1;
- RotateList^[Polygons^[Count].p2] := 1;
- RotateList^[Polygons^[Count].p3] := 1;
- SortCount := SortCount + 1;
- End;
- End;
- For Count := 0 to (NumVert - 1) do
- Begin
- If RotateList^[Count] = 1
- Then Begin
- DotList[Count].Viewer := DotProduct(ObjectViewer, VertNorms^[Count]);
- DotList[Count].XAxis := DotProduct(XAxis, VertNorms^[Count]);
- DotList[Count].YAxis := DotProduct(YAxis, VertNorms^[Count]);
- End;
- End;
- If ShadeType = cGouraudPoly
- Then Begin
- For Count := SortStart to (SortCount-1) do
- Begin
- With GouraudSortRec(SortList^[Count]) do
- Begin
- If DotList[Polygons^[Index].p1].Viewer > 0
- Then C1 := Word(DotList[Polygons^[Index].p1].Viewer)*63 Shr 9
- Else C1 := 0;
- If DotList[Polygons^[Index].p2].Viewer > 0
- Then C2 := Word(DotList[Polygons^[Index].p2].Viewer)*63 Shr 9
- Else C2 := 0;
- If DotList[Polygons^[Index].p3].Viewer > 0
- Then C3 := Word(DotList[Polygons^[Index].p3].Viewer)*63 Shr 9
- Else C3 := 0;
- Base := 64*(SortList^[Count].Index And 1);
- End;
- End;
- End
- Else Begin
- For Count := SortStart to (SortCount-1) do
- Begin
- With SortList^[Count] do
- Begin
- Theta1 := 128 + Integer(DotList[Polygons^[Index].p1].XAxis) Shr 2;
- Phi1 := 128 + Integer(DotList[Polygons^[Index].p1].YAxis) Shr 2;
- Theta2 := 128 + Integer(DotList[Polygons^[Index].p2].XAxis) Shr 2;
- Phi2 := 128 + Integer(DotList[Polygons^[Index].p2].YAxis) Shr 2;
- Theta3 := 128 + Integer(DotList[Polygons^[Index].p3].XAxis) Shr 2;
- Phi3 := 128 + Integer(DotList[Polygons^[Index].p3].YAxis) Shr 2;
- End;
- End;
- End;
- End;
- End;
-
- Procedure GetZMidValues(Num : Integer);
-
- Var
- Count : Integer;
- T1, T2, T3 : Integer;
-
- Begin
- For Count := 0 to (Num-1) do
- Begin
- T1 := VectorObjects[SortList^[Count].OwnerIndex].Polygons^[SortList^[Count].Index].p1;
- T2 := VectorObjects[SortList^[Count].OwnerIndex].Polygons^[SortList^[Count].Index].p2;
- T3 := VectorObjects[SortList^[Count].OwnerIndex].Polygons^[SortList^[Count].Index].p3;
- SortList^[Count].ZMid :=
- Word(VectorObjects[SortList^[Count].OwnerIndex].WorldVert^[T1].z +
- VectorObjects[SortList^[Count].OwnerIndex].WorldVert^[T2].z +
- VectorObjects[SortList^[Count].OwnerIndex].WorldVert^[T3].z)
- Div 3;
- End;
- End;
-
- Procedure DisplayPolygons(PgSeg : Word);
-
- Var
- Radix : Word;
- OI : Integer;
- T1, T2, T3 : Integer;
-
- Begin
- For Radix := 255 downto 0 do
- While MSBList^[Radix] <> Nil do
- Begin
- OI := MSBList^[Radix]^.OwnerIndex;
- T1 := VectorObjects[OI].Polygons^[MSBList^[Radix]^.Index].p1;
- T2 := VectorObjects[OI].Polygons^[MSBList^[Radix]^.Index].p2;
- T3 := VectorObjects[OI].Polygons^[MSBList^[Radix]^.Index].p3;
- If MSBList^[Radix]^.PolyType = cGouraudPoly
- Then Begin
- GouraudClipPolygon(VectorObjects[OI].ScreenVert^[T1].x, VectorObjects[OI].ScreenVert^[T1].y,
- VectorObjects[OI].ScreenVert^[T2].x, VectorObjects[OI].ScreenVert^[T2].y,
- VectorObjects[OI].ScreenVert^[T3].x, VectorObjects[OI].ScreenVert^[T3].y,
- GouraudSortRec(MSBList^[Radix]^).Base+GouraudSortRec(MSBList^[Radix]^).C1,
- GouraudSortRec(MSBList^[Radix]^).Base+GouraudSortRec(MSBList^[Radix]^).C2,
- GouraudSortRec(MSBList^[Radix]^).Base+GouraudSortRec(MSBList^[Radix]^).C3,
- PgSeg);
- End
- Else Begin
- PhongClipPolygon(VectorObjects[OI].ScreenVert^[T1].x, VectorObjects[OI].ScreenVert^[T1].y,
- VectorObjects[OI].ScreenVert^[T2].x, VectorObjects[OI].ScreenVert^[T2].y,
- VectorObjects[OI].ScreenVert^[T3].x, VectorObjects[OI].ScreenVert^[T3].y,
- (MSBList^[Radix]^).Theta1, (MSBList^[Radix]^).Phi1,
- (MSBList^[Radix]^).Theta2, (MSBList^[Radix]^).Phi2,
- (MSBList^[Radix]^).Theta3, (MSBList^[Radix]^).Phi3,
- PgSeg, VectorObjects[OI].EnvMap);
- End;
- MSBList^[Radix] := MSBList^[Radix]^.Next;
- End;
- End;
-
- Procedure DisplayVectorObjects(VPage : Word);
- { Displays all Vector Objects with the enabled bit on }
-
- Var
- Count : Integer;
- SortCount : Integer;
-
- Begin
- SortCount := 0;
- For Count := 0 to 3 do
- Begin
- If VectorObjects[Count].Enabled = 1
- Then Begin
- With VectorObjects[Count] do
- Begin
- ObjectViewer.x := 0; ObjectViewer.y := 0; ObjectViewer.z := -512;
- XAxis.x := -512; XAxis.y := 0; XAxis.z := 0;
- YAxis.x := 0; YAxis.y := -512; YAxis.z := 0;
- SingleRotate(ObjectViewer, (511-xa), (511-ya), (511-za));
- SingleRotate(XAxis, (511-xa), (511-ya), (511-za));
- SingleRotate(YAxis, (511-xa), (511-ya), (511-za));
- CreateRotateList(SortCount, Count);
- InitRotationMatrix(xa, ya, za);
- Rotate(LocalVert^, WorldVert^, ScreenVert^, RotateList^, NumVert, xt, yt, zt);
- End;
- End;
- End;
- GetZMidValues(SortCount);
- ByteSort(SortList^, SortCount, MSBList);
- DisplayPolygons(VPage);
- End;
-
- Begin
- End.